<?php

namespace Account\Model;

use Common\Model\BaseModel;
use Common\Model\ModelException;
use Util\StringUtils;
use Ruben\Yxyun\Yxim;
use Carbon\Carbon;
use Think\Log;

class UsersModel extends BaseModel {

    protected $_auto = [
        ['password', 'encryptPass', self::MODEL_BOTH, 'callback'],
        ['password', '', self::MODEL_UPDATE, 'ignore'],
        ['reg_time', 'time', self::MODEL_INSERT, 'function'],
        ['reg_ip', 'get_client_ip', self::MODEL_INSERT, 'function'],
    ];
    protected $_validate = [
//        ['nickname', 'require', '昵称不能为空'],
        ['mobile', 'checkMobile', '该手机号已被注册', self::MODEL_BOTH, 'callback'],
    ];
    protected $_scope = [
        'valid' => [
            'where' => ['delete_time' => 0]
        ],
    ];

    /**
     * 登录
     * @param array $checkedUser 登录信息
     * @return void
     */
    public function login($user) {
        if ($user['closed'] == 1) {
            throw new ModelException(110031);
        }
        if ($user['state'] == 2) {
            throw new ModelException(30002);
        }
//        $this->saveLoginLog($user['user_id']);//活跃用户统计
        return $user;
    }

    public function saveLoginLog($userId) {
        // 统计活跃人
        $date = date('Ymd');
        $log = M('LoginLog')->where(['user_id' => $userId, 'login_date' => $date])->find();
        D('Users')->where(['user_id' => $userId])->setField([
            'last_time' => time(),
        ]);
        if (empty($log)) {
            M('LoginLog')->add([
                'login_date' => $date,
                'client_ip' => get_client_ip(),
                'create_time' => time(),
                'user_id' => $userId,
            ]);
            return true;
        }
    }

    /**
     * 检查是否有足够的余额
     *
     * @param  integer $uid 用户ID
     * @param  integer $cost 花费的金额
     * @return bool
     */
    public function checkMoney($uid, $cost) {
        $user = D('Users')->find($uid);
        if ($user['money'] >= $cost) {
            return true;
        }
        return false;
    }

    public function loginByMobile($mobile, $password = null, $mobile_cdoe = null) {
        $user = D('Users')->where(['mobile' => $mobile])->find();
        if ($user) {
            if (!empty($mobile_cdoe)) {
                return $this->login($user);
            } elseif (md5($password) === $user['password']) {
                return $this->login($user);
            } else {
                throw new ModelException(50001, '密码错误');
            }
        } else {
            throw new ModelException(30001, '该帐号未注册');
        }
    }

    /**
     * 注册新用户
     *
     * @param string $mobile 手机号
     * @param string $password 原始密码
     * @param string $introducerSk 推荐码
     * @return int
     */
    public function register($mobile = '', $password = '', $nickname = '', $avatar = '', $sex = 1, $introducerSk = 0) {
        $userModel = D('Users');
        if (!empty($mobile)) {
            $user = $userModel->where(['mobile' => $mobile])->find(); //验证手机是否存在
            if ($user)
                throw new ModelException(30001, '该帐号已注册');
        }
        $face = $avatar ? $avatar : 'https://liaoba-dev.oss-cn-shenzhen.aliyuncs.com/images/default.png';
        $userData = [
            'mobile' => $mobile,
            'account' => StringUtils::keyGen(),
            'password' => $password,
            'face' => $face,
            'sex' => $sex,
            'nickname' => $nickname,
        ];
        $data = $userModel->create($userData);
        if ($data) {
            $id = $userModel->add();
            $user = $userModel->find($id);
//            tag('user_register', $user);
            return $this->login($user);
            return $id;
        } else {
            throw new ModelException(30001, $userModel->getError());
        }
    }

    /**
     * @todo redis数据丢失后恢复
     * @param integer $uid 送礼人ID
     * @param integer $nums 增加的贡献度
     * @param integer $anchorId 主播ID
     * @return void
     */
    public function addContribution($uid, $nums, $anchorId) {
        D('Users')->where(['user_id' => $uid])->setInc('contribution', $nums);
        $redis = redis();
        // 日贡献
        $dayName = 'day_contribution_rank:' . date('Ymd');
        $redis->zincrby($dayName, $nums, $uid);
        $redis->expireat($dayName, Carbon::now()->endOfDay()->timestamp);


        // 周贡献
        $weekName = 'week_contribution_rank:' . date('YW');
        $redis->zincrby($weekName, $nums, $uid);
        $redis->expireat($weekName, Carbon::now()->endOfWeek()->timestamp);
        // 总贡献
        $allName = 'all_contribution_rank';
        $redis->zincrby($allName, $nums, $uid);

        // 主播粉丝贡献榜 日 周 总
        $fansOfDay = "anchor_{$anchorId}_fans_ranklist_day" . date('Ymd');
        $redis->zincrby($fansOfDay, $nums, $uid);
        $redis->expireat($fansOfDay, Carbon::now()->endOfDay()->timestamp);
        $fansOfWeek = "anchor_{$anchorId}_fans_ranklist_week" . date('YW');
        $redis->zincrby($fansOfWeek, $nums, $uid);
        $redis->expireat($fansOfWeek, Carbon::now()->endOfWeek()->timestamp);
        $fansOfAll = "anchor_{$anchorId}_fans_ranklist_all";
        $redis->zincrby($fansOfAll, $nums, $uid);
    }

    public function socialLogin($openid, $nickname, $avatar, $sex, $unionid = '', $source = 'weixin') {

        $lock = 'social_lock_' . $openid;
        $user = lock($lock, function() use($source, $openid, $nickname, $avatar, $sex, $unionid) {
            $connect = D('Connect')->where(['type' => $source, 'unionid' => $unionid])->order('connect_id asc')->find();
            $userModel = D('Users');
            if (empty($connect)) {
                $connect = D('Connect')->where(['type' => $source, 'open_id' => $openid])->find();
                if (empty($connect)) {
                    $user = $userModel->socialRegister($source, $openid, $nickname, $avatar, $sex, $unionid);
                } else {
                    $connect['unionid'] = $unionid;
                    D('Connect')->save($connect);
                    $user = $userModel->find($connect['uid']);
                }
            } else {
                $user = $userModel->find($connect['uid']);
            }
            return $user;
        });
        if ($user) {
            return $this->login($user);
        } else {
            throw new ModelException(10006);
        }
    }

    public function bindSocial($source = 'weixin', $openid, $nickname, $avatar = 'default.png', $sex, $unionid = '') {
        try {
            $existConnect = D('Connect')->where(['type' => $source, 'open_id' => $openid])->find();
            if ($existConnect)
                throw new ModelException(30006);
            $uid = $this->user['id'];
            D('Connect')->add(['uid' => $uid, 'open_id' => $openid, 'type' => $source, 'unionid' => $unionid, 'nickname' => $nickname]);
            D('Users')->setField(['user_id' => $uid, 'nickname' => $nickname, 'img' => $avatar, 'sex' => $sex]);
            return true;
        } catch (ModelException $e) {
            throw $e;
        }
    }

    /**
     * 游客登录
     *
     * @return array
     */
    public function visitorLogin() {
        $visitor = [
            'id' => - intval((time() . StringUtils::randString(4, 1))),
            'account' => StringUtils::keyGen(),
            'nickname' => '游客' . time(),
            'status' => 1,
            'face' => '/Uploads/avatar/default.png',
            'online' => 1,
            'level' => 0,
            'intro' => '这人很懒，什么也没有写',
            'is_real' => 0,
            'is_enterprise' => 0,
            'sex' => 1,
            'like_num' => 0,
            'money' => 0,
            'type' => -1,
        ];
        return $this->login($visitor);
    }

    /**
     * 使用社会帐号注册
     *
     * @param string $source 来源 QQ Wechat sina
     * @param string $openid 用来识别社会帐号的ID
     * @param string $nickname 社会帐号的昵称
     * @param string $avatar 社会帐号的头像地址
     * @return int connect id
     */
    public function socialRegister($source, $openid, $nickname, $avatar, $sex = 1, $unionid = '') {
        $user = $this->register('', '', $nickname, $avatar, $sex);
        $connect = [
            'type' => $source,
            'open_id' => $openid, // unionid存在时不使用openid注册
            'unionid' => $unionid,
            'nickname' => $nickname,
            'uid' => $user['user_id'],
        ];
        D('Connect')->add($connect);
        $userinfo = D('Users')->find($user['user_id']);
        return $userinfo;
    }

    public function bindMobile($userId, $mobile) {
        if (D('Users')->where(['mobile' => $mobile])->find()) {
            throw new ModelException(30001, '手机已绑定了帐号');
        }
        D('Users')->where(['user_id' => $userId])->setField('mobile', $mobile);
        return true;
    }

    public function updatePassword($userId, $newPassword) {
        $user = D('Users')->field('user_id,mobile,password')->find($userId);
        if (empty($user['mobile'])) {
            $this->error = '未绑定手机';
            $this->errorCode = 40002;
            return false;
        } else {
            unset($user['mobile']);
        }
        /* 第三方注册的第一次修改密码为空，允许其通过 */
        // if (empty($user['password']) || password_verify($oldPassword, $user['password'])) {
        $user['password'] = $newPassword;
        $userModel = D('Users');
        if ($data = $userModel->create($user)) {
            $userModel->save();
            return true;
        } else {
            $this->errorMessage = $userModel->getError();
            $this->errorCode = 40002;
            return false;
        }
        // } else {
        //     $this->error = '原密码错误';
        //     $this->errorCode = 10004;
        //     return false;
        // }
    }

    public function addPostsCount($userId) {
        D('Users')->where(['user_id' => $userId])->setInc('posts_count');
    }

    public function updateInfo($uid, $params) {
        if (!empty($params['face'])) {
            $params['face'] = uploadBase64toOss($params['face'], 'face_' . $uid);
        }
        if (!empty($params['pay_password'])) {
            $params['pay_password'] = md5($params['pay_password']);
        }
        D('Users')->where(['user_id' => $uid])->setField($params);
        
        if (C('im.open') == 1) {
           $user = D('Users')->where(['user_id' => $uid])->find();
                $imConfig = C('sdk.yxim');
                $yxim = new Yxim($imConfig);
                $accid = $uid;
                $name = $user['nickname']?:'';
                $icon = $user['face']?:'';
                $sign = $user['token']?:'';
                $email = $user['email']?:'';
                $birth = $user['birth']?:'';
                $mobile = $user['mobile']?:'';
                $gender = $user['sex']?:'';
                $result = $yxim->updateUinfo($accid,$name,$icon,$sign,$email,$birth,$mobile,$gender);
            }
        return true;
    }

    /**
     * 使用余额消费
     *
     * @param integer $uid 消费者
     * @param string $type  消费方式 buy_live
     * @param string $mtype  币种 money-秀币 coin-余额
     * @param float $amount 消费金额
     * @param string $remark 备注
     * @return 
     */
    public function costMoney($uid, $type, $amount, $remark, $mtype = 'money', $extra = '') {
        M()->startTrans();
        $user = D('Users')->lock(true)->find($uid);
        $money = $user[$mtype];
        if ($money*100 >= $amount) {
            $userModel = D('Users');
            $res1 = D('Users')->where(['user_id' => $uid])->setDec($mtype, $amount);

            $cashLogModel = D('CashLog');
            $cashLog = [
                'user_id' => $uid,
                'money' => -$amount/100,
                'type' => $type,
                'create_time' => time(),
                'remark' => $remark,
                'mtype' => $mtype,
                'extra' => $extra,
            ];
            if ($data = $cashLogModel->create($cashLog)) {
                $cashLogModel->add();
                M()->commit();
                return true;
            } else {
                M()->rollback();
                throw new ModelException(30000, $cashLogModel->getError());
            }
        } else {
            M()->rollback();
            throw new ModelException(30010, "额度不足($money)");
        }
    }

    public function withdraw($uid, $info) {
        $user = D('Users')->find($uid);
        if ($user['rmoney'] >= $info['amount']) {
            D('Users')->where(['user_id' => $uid])->setDec('money', $info['amount']);
            D('Users')->where(['user_id' => $uid])->setDec('rmoney', $info['amount']);
            /* 平台出出账 */
            D('CashRecord')->add([
                'uid' => $uid,
                'money' => -$info['amount'],
                'type' => 'withdraw',
                'create_time' => time(),
                'from' => $uid,
                'remark' => '提现申请'
            ]);

            M('WithdrawRecord')->add([
                'user_id' => $uid,
                'amount' => $info['amount'],
                'create_time' => time(),
                'finish_time' => 0,
                'status' => 0,
                'bank_card' => $info['bank_card'],
                'real_name' => $info['real_name'],
                'bank_name' => $info['bank_name'],
            ]);
            return true;
        } else {
            $this->errorCode = 40001;
            $this->error = '提现金额不足';
            return false;
        }
    }

    /**
     * 增加余额
     *
     * @param integer $uid 收益人
     * @param string $type charge 充值 recive_gift
     * @param float $amount 金额
     * @param string $remark 备注
     * @param bool withdrawable 可否用于提现
     * @param integer from 来源 0 系统 >0 用户
     * @return void
     */
    public function earnMoney($uid, $type, $amount, $remark, $withdrawable = true, $from = 0) {
        M()->startTrans();
        $userModel = D('Users');
        $user = $userModel->lock(true)->find($uid);
        if ($user) {
            $mtype = 'money';
            if ($withdrawable) {
                $userModel->where(['user_id' => $uid])->setInc('withdrawable_money', $amount);
                $mtype = 'withdrawable_money';
            } else {
                $moneyrate = D('Helper/Setting')->getByKey('moneyrate');
                if ($type === 'charge') {
                    // 比率为1元
//                    $amount = ($amount/100) * ($moneyrate['money_rate'] ? : 1);
                    $userModel->where(['user_id' => $uid])->setInc('money', $amount);
                    $mtype = 'money';
                } elseif ($type === 'mcharge') {
                    $amount *= ($moneyrate['coin_rate'] ? : 1);
                    $userModel->where(['user_id' => $uid])->setInc('coin', $amount);
                    $mtype = 'coin';
                } elseif ($type === 'rewardback') {
                    $userModel->where(['user_id' => $uid])->setInc('coin', $amount);
                    $mtype = 'coin';
                } elseif ($type === 'get_luckmoney') {
                    $userModel->where(['user_id' => $uid])->setInc('money', $amount);
                    $mtype = 'money';
                }
            }

            /* 资金记录 */
            D('CashLog')->add([
                'user_id' => $uid,
                'money' => $amount/100,
                'type' => $type,
                'remark' => $remark,
                'from' => $from,
                'mtype' => $mtype,
                'create_time' => time(),
            ]);
            M()->commit();
            return true;
        }
    }

    public function updatePwd($mobile, $newPassword) {
        $userModel = D('Users');
        $user = $userModel->getByMobile($mobile);
        if ($user) {
            $userModel->where(['mobile' => $mobile])->setField('password', md5($newPassword));
            $user = $userModel->where(['mobile' => $mobile])->find();
            return $user;
        } else {
            throw new ModelException(30009);
        }
    }

    /**
     * 充值入账
     *
     * @param array $paymentLog 支付记录
     * @return boolean
     */
    public function addMoney($paymentLog) {
        $userModel = D('Users');
        // $paymentLog = D('PaymentLog')->find($paymentLogId);
        /* 只有未处理的记录才有效 */
        if ($paymentLog['status'] == 'unpaid') {
            /* 资金入账 */
            $userModel->where(['user_id' => $paymentLog['to_uid']])->setInc('money', $paymentLog['amount']);
            $paymentLogModel = D('PaymentLog');
            $paymentLog['status'] = '2';
            if ($paymentLogModel->create($paymentLog)) {
                $paymentLogModel->save();

                /* 资金记录 */
                $cashRecordData = [
                    'uid' => $paymentLog['to_uid'],
                    'money' => $paymentLog['amount'],
                    'type' => 'charge',
                    'remark' => '平台充值'
                ];
                $cashRecordModel = D('CashRecord');
                if ($cashRecordModel->create($cashRecordData)) {
                    $cashRecordModel->add();
                    return true;
                }
            }
        }
        return false;
    }

    protected function encryptPass($data) {
        return $data ? md5($data) : '';
        // return $data ? password_hash($data, PASSWORD_DEFAULT) : '';
    }

    private function getAccessToken() {
        /* 暂时随便 */
        return md5(time());
    }

    /* 登入和注册 */

    public function loginAndRegister($mobile) {
        $user = D('Users')->where(['mobile' => $mobile])->find();
        if ($user) {//走登入
         throw new ModelException(30001, '该帐号已注册');
//            return $this->login($user);
        }

        return $this->register($mobile);
    }

    protected function checkMobile($mobile) {
        if ($mobile) {
            $user = D('Users')->getByMobile($mobile);
            return empty($user);
        }
        return true;
    }

    protected function _after_find(&$record, $options) {

        if ($record['money']) {
            $record['money'] = strval($record['money'] / 100);
        }
        if (isset($record['face'])) {
            if ($record['face'] == 'default.png')
                $record['face'] = 'https://jinshimall.oss-cn-shenzhen.aliyuncs.com/images/5bdbdb8f432e2.jpg';
            $record['face'] = auto_prefix($record['face']);
        }
    }

    protected function _after_select(&$records, $options) {
        $user = get_user();
        foreach ($records as &$record) {
            if ($record['money']) {
                $record['money'] = strval($record['money'] / 100);
            }
            if (isset($record['face'])) {
                if ($record['face'] == 'default.png')
                    $record['face'] = 'https://jinshimall.oss-cn-shenzhen.aliyuncs.com/images/5bdbdb8f432e2.jpg';
                $record['face'] = auto_prefix($record['face']);
            }
        }
    }

}
